<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Generator</title>
  </head>
  <body>
    <!-- 

      Async是如何被JavaScript实现的
      Generator 基本使用
      参考文章: https://zhuanlan.zhihu.com/p/473245486

     -->
    <script>
      /**
       * 生成器基本使用
       * **/
      function* gen() {
        yield 1;
        yield 2;
        yield 3;
      }

      const g = gen();
      console.log(g.next()); // {value:1,done:false}
      console.log(g.next()); // {value:2,done:false}
      console.log(g.next()); // {value:3,done:false}
      console.log(g.next()); // {value:undefined,done:true}
    </script>

    <script>
      /**
       * 函数返回值
       * **/
      function* gen2() {
        const a = yield 1;
        console.log(a, 'this a');
        const b = yield 2;
        console.log(b, 'this b');
        const c = yield 3;
        console.log(c, 'this c');
        return 'returnValue';
      }
      const g2 = gen2();
      console.log(g2.next());
      console.log(g2.next('param a'));
      console.log(g2.next('param b'));
      console.log(g2.next('param c'));
    </script>

    <script>
      function promise1() {
        return new Promise((reslove, reject) => {
          setTimeout(() => {
            reslove('promise 1');
          }, 1000);
        });
      }

      function promise2(value) {
        return new Promise((reslove, reject) => {
          setTimeout(() => {
            reslove('promise 2' + value);
          }, 2000);
        });
      }

      function* readGen() {
        const p1 = yield promise1();
        const p2 = yield promise2(p1);
        return p2;
      }

      function asyncGen(fn) {
        const read_gen = fn();

        return new Promise((reslove, reject) => {
          read_gen.next().value.then((ret) => {
            read_gen.next(ret).value.then((ret) => {
              reslove(read_gen.next(ret));
            });
          });
        });
      }

      asyncGen(readGen).then((value) => {
        console.log(value);
      });
    </script>

    <script>
      // 通用函数
      // async await 转为低级语法后的实现就是类型下面 co 函数的
      function co(fn) {
        const gen = fn();
        console.log(gen);
        function next(param, reslove) {
          const { done, value } = gen.next(param);
          if (!done) {
            Promise.resolve(value).then((ret) => next(ret, reslove));
          } else {
            reslove(value);
          }
        }
        return new Promise((reslove, reject) => next(void 0, reslove));
      }

      co(readGen).then((ret) => {
        console.log('co', ret);
      });
    </script>
  </body>
</html>
